/*
* this file descripe the function and the structures of 
* usb device function 
* 
* by zsw 2008.4.25
*/
#include "common.h"
#include "chap9.h"

USB_DEVICE_DESCRIPTOR DeviceDescr =//<<
{
	18,//sizeof(USB_DEVICE_DESCRIPTOR),
	USB_DEVICE_DESCRIPTOR_TYPE,
	0x10,//SWAP(0x200),	//Complient to USB2.0 FullSpeed
	0x01,
	0x00,//bDeviceClass,
	0x00,//bDeviceSubClass,
	0x00,//bDeviceProtocol,
	0x40,//EP0_PACKET_SIZE,
	0x71,//SWAP(0x4cc), // Vendor ID for PHILIPS
	4,
	0x66,//SWAP(0x1a62),// Product ID for ISP 1362
	0x6,
	0x0,//SWAP(0x0100),// Device Release Number 1.0
	1,
	0,//STR_INDEX_MANUFACTURER,
	0,//STR_INDEX_PRODUCT,
	0,//STR_INDEX_SERIALNUMBER,
	0x1
  
};

USB_CONFIGURE_DESCRIPTOR configureDescriptor =
{
	0x09,//sizeof(usb_configure_descriptor)
	0x02,//configure descriptor
	0x0000 + 9 + 9 + 7*2,// total conf descriptor length
	0x01,//num interface
	0x01,//conf index
	0x00,//index of string descriptor of the conf descriptor
	0x80,//
	0x32//power 500 mA	
};

USB_INTERFACE_DESCRIPTOR interfaceDescriptor =
{
	0x09,//sizeof(usb interface descriptor)
	0x04,//interface
	0x00,//interface num
	0x00,//interface alternate index
	0x02,//num endpoints
	0x08,//interface class
	0x04,//SCSI subclass
	0x50,//bulk only
	0x00//index of string descriptor
};


USB_ENDPOINT_DESCRIPTOR endpoint_1_in_descriptor = {
	7,												// Size of this descriptor
	0x05,			// Endpoint descriptor type
	0x81,											// Endpoint address = 1,direction in
	0x02,					// Transfer type (BULK)
	EP1_PACKET_SIZE,							// Max packet size (64bytes)
	0												// Interval
};

// EPd Endpoint descriputor
USB_ENDPOINT_DESCRIPTOR endpoint_2_out_descriptor = {
	7,												// Size of this descriptor
	0x05,			// Endpoint descriptor type
	0x02,											// Endpoint address = 2,direction out
	0x02,					// Transfer type(bulk)
	EP1_PACKET_SIZE,							// Max packet size (64bytes)
	0												// Interval
};










int analyseUsbRequest(char* request)
{
#if USB_ENU_DEBUG
	printf("request->bRequest : %x\n",request[1]);
	printf("request->bRequest origin: %x\n",request[1]);
#endif
	char data;
	data = (char)request[1];
	switch( data ){
		case 0:
			return GET_STATUS;
		case 1:
			return CLEAR_FEATURE;
		case 3:
			return SET_FEATURE;
		case 5:
			return SET_ADDRESS;
		case 6:
			return GET_DESCRIPTOR;
		case 7:
			return SET_DESCRIPTOR;
		case 8:
			return GET_CONFIGURATION;
		case 9:
			return SET_CONFIGURATION;
		case 10:
			return GET_INTERFACE;
		case 11:
			return SET_INTERFACE;
		case 12:
			return SYNCH_FRAME;
		default:
			return -1;
		}
}
int analyseUsbClassRequest(char *request)
{
	short data;
	data = 0x00ff & request[1];
#if USB_ENU_DEBUG
	printf("class bRequest:%x\n",data);
#endif
	switch (data){
		case 0x0ff:
			return BULK_ONLY_MASS_STORAGE_RESET;
		case 0x0fe:
			return GET_MAX_LUN;
		default:
			return -1;
		}


}
int doUsbStandardRequest(usbEnuFsm * usbEnuStatus)
{
	switch(usbEnuStatus->usbRequest){
		case GET_DESCRIPTOR:
#if USB_ENU_DEBUG
			uartPrintf("Get descriptor\n");
			printf("Get descriptor\n");
#endif
			usbGetDescriptor(usbEnuStatus);
			usbEnuStatus->fsmStatus = USB_CONTROL_HANDSHAKE;//USB_CONTROL_NONDATA;
			break;
		case GET_STATUS:
#if USB_ENU_DEBUG
			uartPrintf("Get status\n");
			printf("Get status\n");
#endif
			usbGetStatus(usbEnuStatus);
			usbEnuStatus->fsmStatus = USB_CONTROL_HANDSHAKE;
			break;
		case SET_ADDRESS:
#if USB_ENU_DEBUG
			uartPrintf("Set address\n");
			printf("Set address\n");
#endif
			usbSetAddress(usbEnuStatus);
			usbEnuStatus->fsmStatus = USB_CONTROL_HANDSHAKE;
			break;
		case SET_CONFIGURATION:
#if USB_ENU_DEBUG
			uartPrintf("Set configuration\n");
			printf("Set configuration\n");
#endif
			usbSetConfiguration(usbEnuStatus);
			//usbEnuStatus->fsmStatus = USB_CONTROL_SET;
			usbEnuStatus->fsmStatus = USB_CONTROL_HANDSHAKE;
			break;
		case CLEAR_FEATURE:
#if USB_ENU_DEBUG
			uartPrintf("Clear Feature\n");
			printf("Clear Feature\n");
#endif	
			usbClearFeature(usbEnuStatus);
            break;
		
		default:
			return -1;
		}
}
void usbMassStorageReset(void)
{
	usb_1362_epx_transmit(0,0,0);
}

void	usbGetMaxLun(void)
{
	char lunNum = 1;
	usb_1362_epx_transmit(0,&lunNum,1);
}
int doUsbClassRequest(usbEnuFsm * usbEnuStatus)
{
	switch(usbEnuStatus->usbClassRequest){
		case BULK_ONLY_MASS_STORAGE_RESET:
			printf("bulk mass storage RESET!\n");
			usbMassStorageReset();
			return 1;
		case GET_MAX_LUN:
			printf("Get Max Lun!\n");	
			usbGetMaxLun();
			return 1;
		default:
			return 0;
		}

}
int usbClearFeature(usbEnuFsm * usbEnuStatus)
{
	if((usbEnuStatus->rxBuf[4] +usbEnuStatus->rxBuf[5]*64) == 0){
		/*Clear Endpoint Feature */
		printf("Clear Endpoint Feature\n");
		// UNSTALL ENDPOINT
		usb_1362_epx_unstall(EP1);
		usb_1362_epx_unstall(EP2);	
		usb_1362_epx_transmit(0,0,0);
	}
	else
		printf("Clear Device Feature\n");
		usb_1362_epx_transmit(0,0,0);
}
int usbGetDescriptor(usbEnuFsm * usbEnuStatus)
{
	static char configurationDes[9+9+7*2];
	char index;
	index = 0x0ff & (char)((usbEnuStatus->rxBuf)[3]);
	switch(index){
		case 0x01:
			printf("get device descriptor\n");
			usb_1362_epx_transmit(0, (char *)&DeviceDescr,sizeof(USB_DEVICE_DESCRIPTOR));
			break;
		case 0x02:
			printf("Get configration descriptor\n");
			memcpy(configurationDes,&configureDescriptor,9);
			memcpy(configurationDes + 9,&interfaceDescriptor,9);
			memcpy(configurationDes + 9 + 9,&endpoint_1_in_descriptor,7);
			memcpy(configurationDes + 9 + 9 + 7,&endpoint_2_out_descriptor,7);
#if USB_ENU_DEBUG
			printf("config descriptor length:%d\n",sizeof(configurationDes));
#endif			
			if((short)*((usbEnuStatus->rxBuf)+6) < sizeof(configurationDes))
				usb_1362_epx_transmit(0, (char *)&configurationDes,(short)*((usbEnuStatus->rxBuf)+6));
			else
				usb_1362_epx_transmit(0, (char *)&configurationDes,sizeof(configurationDes));
		default:
			break;
		}

}

int usbGetStatus(usbEnuFsm * usbEnuStatus)
{
	char buf[2];
	char data;
	data = 0x0ff & usbEnuStatus->rxBuf[0];
	printf("-----------GetStatus:buf[0] 0x%x\n",data);
	if (data & 0x00){
		buf[0] = 2;
		buf[1] = 0;
		}
	else if(data & 0x1){
		buf[0] = 0;
		buf[1] = 0;
		}
	else if(data & 0x2){
		buf[0] = 0;
		buf[1] = 0;
		}		
	usb_1362_epx_transmit(0, (char *)buf,2);
}
int usbSetAddress(usbEnuFsm * usbEnuStatus)
{
	short address;
	usbDeviceRequest * request;
	request = (usbDeviceRequest *)(usbEnuStatus->rxBuf);
	address = request->wValue;
	printf("USB Address:%x\n",address);
	usb_1362_set_address(address|0x80);
	usb_1362_epx_transmit(0, &address,0);	
	return 1;

}

int usbSetConfiguration(usbEnuFsm * usbEnuStatus)
{
	short config;
	/*usb device configuration*/
	usb_1362_device_init();
	usleep(100);
	usb_1362_epx_transmit(0,&config,0);	
	return 1;
}



